#pragma once

#include "BasicType.h"

namespace LightPlayer{

#define deref_as(TYPE,POINTER) (*((TYPE*)POINTER))

	class Stream{
		const uint8*	m_pBuffer;				// 4
		const uint8*	m_pCurrentPosition;		// 4
		uint32			m_iBufferSize;			// 4
		uint8			m_current_byte;			// 1
		uint8			m_unused_bits;			// 1
												// = 14 byte
	private:
		const uint8* moveOf( uint32 numberOfByte );
	public:
		uint32 getCurrentOffset() const;
		const uint8* getCurrentPosition() const;

		Stream( const uint8* i_pData = NULL, const uint32 i_iBufferSize = 0 );
		void init( const uint8* i_pData = NULL, const uint32 i_iBufferSize = 0 );

		bool isFinish();

		bool	read_bool();
		uint32	read_uint(int32 bitcount);
		int32	read_sint(int32 bitcount);
		float	read_fixed16();
		float	read_fixed();
		float	read_float16();
		float	read_float();
		double	read_double();
		uint8	read_u8();
		int8	read_s8();
		uint16	read_u16();
		int16	read_s16();
		uint32	read_u32();
		int32	read_s32();
		
		void	skip_byte(int32 byte_count);

		void	align();
		bool	isAlign() const;

		void	gotoOffset( uint32 offset );
		void	rewind();
		uint32  getBufferSize() const;
	};

	inline uint32 Stream::getCurrentOffset() const {
		return (m_pCurrentPosition - m_pBuffer);
	}

	inline const uint8* Stream::getCurrentPosition() const {
		return m_pCurrentPosition;
	}

	inline bool Stream::isFinish(){
		return (getCurrentOffset() >= m_iBufferSize-1);
	}

	inline void Stream::align() { 
		m_unused_bits = 0; m_current_byte = 0; 
	}

	inline bool Stream::isAlign() const { 
		return ( (m_unused_bits == 0) && (m_current_byte == 0) );
	}

	inline void	Stream::rewind(){
		gotoOffset(0);
	}

	inline void	Stream::gotoOffset( uint32 offset ){
		align();
		m_pCurrentPosition = m_pBuffer;	
		moveOf( offset );
	}

	inline uint32 Stream::getBufferSize() const{
		return m_iBufferSize;
	}
};